using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace org.synthful.Windows.Forms
{
    /// <summary>
    /// Offered under Apache Public Licence 2.0
    /// synthful.org
    /// blessedgeek [@] synthful.org
    /// 
    /// Description:
    /// Base class for menus with standard Synthful mouse behaviour.
    /// </summary>
    public delegate void
        PopupMenuItemMouseEventHandler(
            PopupMenuItem item, MouseEventArgs args);

    public delegate void
        PopupMenuFileItemMouseEventHandler(
            PopupMenuFileItem item, MouseEventArgs args);

    public partial class PopupMenu : ContextMenuStrip
    {
        public PopupMenuItemMouseEventHandler PopupMenuItemMouseClick;
        public PopupMenuFileItemMouseEventHandler PopupMenuFileItemMouseClick;

        #region Constructors
        public PopupMenu()
        {
            InitializeComponent();
        }

        public PopupMenu(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }

        public PopupMenu(bool showcancel)
        {
            InitializeComponent(showcancel);
        }

        public PopupMenu(IContainer container, bool showcancel)
        {
            container.Add(this);
            InitializeComponent(showcancel);
        }

        /*
        public PopupMenu(string path, bool showcancel)
        {
            InitializeComponent(showcancel);
            FileInfo fi = new FileInfo(path);
            this.Text = fi.Name;
            if (Directory.Exists(path))
                addPathItems(path);
            else if (File.Exists(path))
            {
                this.addPathItem(path);
            }
        }

        protected void addPathItems(string path)
        {
            string[] dirs = Directory.GetDirectories(path);
            foreach(string d in dirs)
            {
                this.addPathItem(d);
            }

            string[] files = Directory.GetFiles(path);
            foreach (string f in files)
            {
                this.addPathItem(f);
            }
        }

        protected void addPathItem(string path)
        {
            PopupMenuItem menu = new PopupMenuItem(path);
            this.addItem(menu);
        }
        */

        #endregion Constructors

        public int FirstItemIndex, LastItemIndex;

        public void addItems(PopupMenuItem[] items)
        {
            if (items == null || items.Length == 0)
                return;

            for (int i = 0; i < items.Length; i++)
                this.addItem(items[i]);
        }

        public void addItem(PopupMenuItem item)
        {
            this.Items.Insert(LastItemIndex++, item);
        }

        public void insertItems(PopupMenuItem[] items)
        {
            if (items == null || items.Length == 0)
                return;

            for (int i = 0; i < items.Length; i++)
                this.insertItem(FirstItemIndex + i, items[i]);
        }

        public void insertItem(int position, PopupMenuItem item)
        {
            this.Items.Insert(position, item);
            LastItemIndex++;
        }

        #region Events & Override Triggers
        public bool cancelItemClicked(ToolStripItemClickedEventArgs e)
        {
            base.Close();
            try
            {
                (this.OwnerItem.Owner as PopupMenu).Cancel.Action(e);
            }
            catch { }
            //base.OnItemClicked(e);
            return false;
        }

        override protected void OnItemClicked(ToolStripItemClickedEventArgs e)
        {
            // if item is a PopupMenuItem
            if (typeof(PopupMenuItem).IsAssignableFrom(e.ClickedItem.GetType()))
            {
                try
                {
                    PopupMenu rootPopup = ((PopupMenuItem)OwnerItem).RootDropDown;
                    if (rootPopup != this)
                        rootPopup.OnItemClicked(e);
                }
                catch { }

                this.onPopupMenuItemClicked(e);

                //this.NonCancelActionPerformed = false;
                // otherwise, menu stays put
                this.ItemClickedButton = MouseButtons.None;
                return;
            }

            this.NonCancelActionPerformed = false;
            // otherwise, execute event delegates as usual
            base.OnItemClicked(e);
            this.ItemClickedButton = MouseButtons.None;
        }

        private void onPopupMenuItemClicked(ToolStripItemClickedEventArgs e)
        {
            // execute event delegates only when left button click
            bool leftClick =
                this.ItemClickedButton == MouseButtons.Left;

            // execute event delegates only when right button click
            bool rightClick =
                this.ItemClickedButton == MouseButtons.Right;

            if (leftClick)
            {
                this.OnItemLeftClicked(e);
                //this.NonCancelActionPerformed = true;

                if (this.ActiveItemLeftClick)
                {
                    base.OnItemClicked(e);
                    //this.cancelItemClicked(e);
                    this.ItemClickedButton = MouseButtons.None;
                    return;
                }
            }

            if (rightClick)
            {
                this.OnItemRightClicked(e);
                this.NonCancelActionPerformed = true;

                if (this.ActiveItemRightClick)
                {
                    base.OnItemClicked(e);
                    this.ItemClickedButton = MouseButtons.None;
                    return;
                }
            }
        }

        virtual protected void OnItemLeftClicked(ToolStripItemClickedEventArgs e)
        {
            if (this.ButtonToSetDefaultItem == MouseButtons.Left)
                this.CheckUnCheckItem(e.ClickedItem as PopupMenuItem);
        }

        virtual protected void OnItemRightClicked(ToolStripItemClickedEventArgs e)
        {
            if (this.ButtonToSetDefaultItem == MouseButtons.Right)
                this.CheckUnCheckItem(e.ClickedItem as PopupMenuItem);
        }

        protected bool CheckUnCheckItem(PopupMenuItem item)
        {
            if (item == null || object.ReferenceEquals(item, this.Cancel))
                return false;

            if (item.Checked)
                Uncheck(item);
            else
                CheckItem(item);

            return item.Checked;
        }

        protected void Uncheck(PopupMenuItem item)
        {
            item.Checked = false;
            if (this.Items.Count>0 && 
                typeof(PopupMenuItem).IsAssignableFrom( this.Items[0].GetType())
                )
            {
                this.DefaultItem = Items[0] as PopupMenuItem;
                this.DefaultItem.Checked = true;
            }
            else
                this.DefaultItem = null;
        }

        protected void CheckItem(PopupMenuItem item)
        {
            // Use theDefaultItem rather than DefaultItem to avoid circular references
            // because DefaultItem{get;} uses this method.
            if (this.theDefaultItem == null ||
                !object.ReferenceEquals(this.DefaultItem.Checked, item)
                )
            {
                if (this.theDefaultItem != null)
                    this.theDefaultItem.Checked = false;
                item.Checked = true;
                this.theDefaultItem = item;
            }
        }

        #endregion Events & Override Triggers
    }
}
